import xID from "./xID.js";
import {isImg,replaceByObj} from "./xUtil.js" ;
import {findJsonByCode} from "./treeUtil.js";

const tmplBase = `
        <div  class="{{class}}">
             <div type="head" class="xhead">   
                  <input key ="input" class="xinput-icon" /> 
                  <i class="iconfont icon-dropdown after-icon-set"></i> 
             </div> 
             <div type="main" style="display:none" class="xmain">
                 <ul type="ul">
                 </ul>
             </div>
        </div>`;

const tmplLi= '<li data-code="{{code}}" type="{{type}}">{{item}}</li>';
const tmplName ='<span type="name">{{name}}</span>';
const tmplIcon = ' <i class="iconfont {{icon}}"></i>';
const tmplImg  = '<img src="{{icon}}" />';
const tmplItem = '{{icon}}{{name}}';
const tmplTitle = 'title="{{title}}"';

export default class xSelect {
    /* 定义变量 开始*/
    // jquery 对象

    $root;
    $head;
    $main;
    $ul;
    $input;
    vBindEvent;
    vCfg;
    vSelect;
    vData;
    vClickId = 'click.'+xID.getID()
    vDropActive=-1;
    /* 定义变量 结束*/

    constructor(cfg) {
        this.$root = $('#' + cfg.el);
        this.$root.html(tmplBase.replace('{{class}}', cfg.style||'select'));
        this.vCfg = cfg;
        this.init();
    };

    /* 渲染区块 开始 */
    init() {
        this.$head = this.$root.find('[type="head"]');
        this.$main = this.$root.find('[type="main"]');
        this.$ul = this.$root.find('[type="ul"]');
        //this.$root.on('click',this.evActive.bind(this));
        this.$input = this.$root.find('input');
        this.$input.on('focus',this.evFocus.bind(this));
        this.$input.on('input',this.evInput.bind(this));
        this.$input.on('keydown',this.evKeydown.bind(this));
        this.$ul.on('click','[type="item"]',this.evDataClick.bind(this));
        if(this.vCfg.placeholder){
            this.$input.attr('placeholder',this.vCfg.placeholder);
        }

        let title ='';
        if(this.vCfg.title)
            title = tmplTitle.replace("{{title}}",this.vCfg.title);
        this.$head.attr("title",title);
        if(this.vCfg.placeholder)
            this.$input.attr("placeholder",this.vCfg.placeholder);
        if(this.vCfg.active)
            this.initValue(this.vCfg.active);
    };

    renderStatus(action,status){
        if(action=='add'){
            this.$head.addClass(status);
        }else{
            this.$head.removeClass(status);
        }
    }

    initValue(value){
        if((this.vCfg.valueType||'code') =='code')
            this.vSelect = findJsonByCode(this.vCfg.data,value)
        else
            this.vSelect = value;
        let val = this.vSelect?(this.vSelect.name||this.vSelect.code||''):'';
        this.$input.val(val);
        this.verify();
    }

    renderUl(mData){
        let lis='';
        //let mData = this.matchData();
        if(mData && mData.length>0){
            for(let data of mData){
                lis +=  this.renderLi(data);
            }
        }
        return lis;
    };

    renderLi(data){
        let item = this.renderItem(data);
        let type = data.type=='tag'?'tag':'item';
        return replaceByObj(tmplLi,{code:data.code,item,type});
    }

    renderItem(data){
        let name  = tmplName.replace('{{name}}',data.name||data.code);
        let icon ='';
        if(data.icon){
            if(isImg(data.icon))
                icon = tmplImg.replace('{{icon}}',data.icon)
            else
                icon = tmplIcon.replace('{{icon}}',data.icon)
        }
        return replaceByObj(tmplItem,{icon,name});
    }

    mainShow(isInput){
        this.vDropActive = -1;
        let mData ;
        if(isInput){
            mData = this.matchData();
            if(this.vSelect && (this.vSelect.name||this.vSelect.code) != this.$input.val())
                this.vSelect = null;
        }
        else
            mData = this.vCfg.data;

        let ul= this.renderUl(mData);
        if(ul){
            this.$ul.html(ul);
            this.$main.show();
        }

    }

    evActive(e){
        this.renderStatus("add","active");
        $(document).on(this.vClickId,this.evOff.bind(this));
    }

    evFocus(e){
        this.mainShow();
        this.evActive(null);
    }

    evInput(e){
        this.mainShow(true);
    }

    evKeydown(e){
        let keynum = window.event ? e.keyCode : e.which;
        switch(keynum){
            //enter
            case 13:
                if(this.vSelect && this.$input.val() != (this.vSelect.name||this.vSelect.code))
                     this.vSelect=null;
                this.$main.hide();
                break;
                //up
            case 38:
                //down
            case 40:
                this.activeItem(keynum);
                break;
            //tab 失去焦点
            case 9:
                this.evOff(e);
                break;
            case 27:
                this.$main.hide();
                break;
        }
    }

    activeItem(keynum){
        let all = this.$ul.find('[type="item"]');
        //let index;
        let oldIndex =-1;
        if(this.vDropActive<0){
            this.vDropActive = keynum==38?all.length-1:0
        }
        else{
            oldIndex = this.vDropActive;
            this.vDropActive = keynum==38?this.vDropActive-1:this.vDropActive+1;
            this.vDropActive =this.vDropActive%all.length;
            if(this.vDropActive<0)
                this.vDropActive = all.length+this.vDropActive;
        }

        if(oldIndex>-1){
            $(all[oldIndex]).removeClass("active");
        }
        $(all[this.vDropActive]).addClass("active");
        let Y= all[this.vDropActive].offsetTop-this.$main[0].offsetTop;
        this.$main.scrollTop(Y);
        //
        let code = all[this.vDropActive].getAttribute("data-code");
        this.vSelect  =  findJsonByCode(this.vCfg.data,code);
        this.$input.val(this.vSelect.name||this.vSelect.code)
        if(this.vBindEvent){
            if((this.vCfg.valueType||'code') =='code')
                this.vBindEvent(this.vSelect.code)
            else
                this.vBindEvent(this.vSelect);
        }

    }

    evDataClick(e){
        let code =e.currentTarget.getAttribute("data-code");
        this.vSelect = findJsonByCode(this.vCfg.data,code);
        this.$input.val(this.vSelect.name);
        this.$main.hide();
        if(this.vBindEvent){
            if((this.vCfg.valueType||'code') =='code')
                this.vBindEvent(this.vSelect.code)
            else
                this.vBindEvent(this.vSelect);
        }
    }

    evOff(e){
        if(!e || this.$root.find(e.target).length<1){
            if(!this.vSelect){
                this.$input.val('');
            }
            this.renderStatus('remove','active');
            this.verify();
            this.$main.hide();
            $(document).off(this.vClickId);
        }
    }


    matchData(){
        let val = this.$input.val().toLowerCase() ;
        if(val){
           let data = [] ;
           if(this.vCfg.data){
               for(let d of this.vCfg.data){
                   if(d.type!='tag'){
                       let ok =false;
                       if(d.name.toLowerCase().match(val))
                           ok = true;
                       if(d.pinyin && d.pinyin.toLowerCase().match(val))
                           ok = true;
                       if(ok)
                           data.push(d);
                   }

               }
           }
           return data;
        }
        else
            return this.vCfg.data;
    }

    setBindEvent(event){
        this.vBindEvent = event;
    };

    setValue(value){
        this.initValue(value);
    };

    setData(data){
        this.vCfg.data =data;
    }

    verify() {
        let result = true;
        if(this.vCfg.mandatory ){
            if(!this.vSelect || this.vSelect.length<1){
                this.renderStatus("remove",'valid');
                this.renderStatus("add","invalid");
                result =false
            }else {
                this.renderStatus("remove",'invalid');
                this.renderStatus("add","valid");
            }
        }
        return result;
    }

    getSelect(){
        return this.vSelect;
    }

}